Snowflakeの「Masking Policy」と「Row Access Policy」を試してみた #SnowflakeDB
※本エントリは、Snowflakeをもっと使いこなそう! Advent Calendar 2022の12日目の記事となります。
さがらです。
Snowflakeの「Masking Policy」と「Row Access Policy」を試してみたので、その内容をまとめてみます。
Masking Policyとは
Masking Policyは、SnowflakeのDynamic Data Maskingを適用させる際に必要なポリシーです。
例えば、Dynamic Data Maskingをあるカラムに対して適用することで、Aというロールには全ての値を見せるが、Bというロールにはすべて「*」などでマスキングした値を見せる、ということが可能です。
Masking Policyのサンプル
以下では、FIRST_NAME
というカラムにおいて、sagara_admin_role
には値を見せるが、それ以外のロールには「*********」を表示する、というMasking Policyを作成し適用しています。
-- Masking Policyの作成と適用に、必要な権限の付与 use role accountadmin; grant create masking policy on schema sagara_rawdata_db.jaffle_shop to role sagara_admin_role; grant apply masking policy on account to role sagara_admin_role; -- Masking Policyの作成 use role sagara_admin_role; create or replace masking policy first_name_mask as (val string) returns string -> case when current_role() in ('SAGARA_ADMIN_ROLE') then val else '*********' end; -- 対象のカラムへ適用 alter table if exists customers modify column first_name set masking policy first_name_mask;
実際にクエリを発行してみると、この様になります。
- カラムの値を見ることが出来る
sagara_admin_role
からのクエリ実行
-- カラムの値を見ることが出来るロールでの実行 use role sagara_admin_role; select * from customers;
- カラムの値を見ることが出来ない
sagara_dev_role
からのクエリ実行
-- カラムの値を見ることが出来ないロールでの実行 use role sagara_dev_role; select * from customers;
Row Access Policyとは
Row Access Policyは、Snowflakeにおいてレコードレベルのアクセス制御を適用させる際に必要なポリシーです。
例えば、使用しているロールと各テーブルのレコードに含まれる部署などのカラムを紐づけて、あるロールの人にはこの部署のレコードだけを見せる、といったことが可能です。
Row Access Policyのサンプル
以下では、sagara_admin_role
には全レコードの値を見せるが、それ以外のロールには全レコード見せない、というRow Access Policyを作成し適用しています。 ※あくまで今回は検証のため、一番手っ取り早い方法を試しています。実際にはマッピングテーブルと併せて、特定のレコードのみにアクセスさせるユースケースの方が多いと思います。
※今回使用するsagara_admin_role
は対象のスキーマの所有者権限を持っているので、CREATE ROW ACCESS POLICY
権限も自動でついてきます。対象のスキーマへの所有者権限を持たないロールでポリシーを定義する場合は、この権限の付与を忘れずにしましょう。
-- Row Access Policyの作成 use role sagara_admin_role; create or replace row access policy row_access_only_sagara_admin as (check_first_name varchar) returns boolean -> case when 'SAGARA_ADMIN_ROLE' = current_role() then true else false end ;
実際にクエリを発行してみると、この様になります。
- 値を見ることが出来る
sagara_admin_role
からのクエリ実行
-- 値を見ることが出来るロールでの実行 use role sagara_admin_role; select * from customers;
- 値を見ることが出来ない
sagara_dev_role
からのクエリ実行
-- 値を見ることが出来ないロールでの実行 use role sagara_dev_role; select * from customers;
2つのポリシーを適用する際の注意
このように非常に便利なMasking PolicyとRow Access Policyですが、同時に適用する場合には注意しないといけないことがあります。
公式Docに記載されている注意事項について記しておきます。
同じカラムに対してMasking PolicyとRow Access Policyは付与できない
Masking PolicyとRow Access Policyですが、1つのカラムに対してこれらのポリシー両方を付与することが出来ません。
実際私も検証をしている中で、すでにMasking Policyを適用中のfirst_name
カラムにRow Access Policyを適用しようとしたところ、下図のようにエラーとなりました
あるテーブルにMasking PolicyとRow Access Policyがどちらも設定されている場合、Row Access Policyが優先して評価される
サブタイトルのとおりですが、あるテーブルにMasking PolicyとRow Access Policyがどちらも設定されている場合、Row Access Policyが優先して評価されます。
例えば、下記のクエリを順番に実行して、あるテーブルにMasking PolicyとRow Access Policyをどちらも適用したとします。
-- Masking Policyの作成 use role sagara_admin_role; create or replace masking policy first_name_mask as (val string) returns string -> case when current_role() in ('SAGARA_ADMIN_ROLE') then val else '*********' end; -- Masking Policyを対象のカラムへ適用 alter table if exists customers modify column first_name set masking policy first_name_mask; -- Row Access Policyの作成 use role sagara_admin_role; create or replace row access policy row_access_only_sagara_admin as (check_first_name varchar) returns boolean -> case when 'SAGARA_ADMIN_ROLE' = current_role() then true else false end; -- Row Access Policyを対象のカラムへ適用 use role sagara_admin_role; alter table customers add row access policy jaffle_shop.row_access_only_sagara_admin on (last_name);
この上で、下記のクエリを実行すると、Row Access Policyの方が先に適用され、結果欄には何も出てこなくなります。
-- どちらのポリシーでも値を見ることが出来ないロールでの実行 use role sagara_dev_role; select * from customers;
最後に
SnowflakeのMasking PolicyとRow Access Policyを試してみました。どちらも元データを書き換えることなく動的に対応してくれる機能なので非常に便利ですが、上述の通り同時に適用する場合には注意したいですね。
Masking Policyについては、現在(2022年12月1日時点)はタグを介した付与も可能なので、この機能も近日中に試してみます!